home *** CD-ROM | disk | FTP | other *** search
- /* ppmtopcx.c - read a portable pixmap and produce a PCX file
- **
- ** Copyright (C) 1990 by Michael Davidson.
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <appkit/NXBitmapImageRep.h>
- #include <streams/streams.h>
- #include "pcxlib.h"
- #include "kludge.h"
-
- #define MAXCOLORS 256
- #define MAXPLANES 4
-
- #define cht 0
- #define ppm_lookupcolor(a,b) 0
-
- typedef void (* vfunptr)( int, int, unsigned char*, int, int );
-
- /*
- * Pointer to function returning an int
- */
- static void PCXEncode( NXStream * fp,
- int GWidth,
- int GHeight,
- int Colors,
- unsigned char Red[],
- unsigned char Green[],
- unsigned char Blue[],
- vfunptr GetPlanes);
- static void PutPlane ( NXStream *fp,
- unsigned char *buf,
- int Size );
- static void ReadPlanes( int y,
- int width,
- unsigned char *buf,
- int planes,
- int bits);
- static void Putword( int w,
- NXStream *fp);
- static void Putbyte( int b,
- NXStream *fp );
-
- static unsigned char *picData;
-
- void pcxwrite(NXStream *ifp,
- unsigned char *data,
- unsigned char r[256],
- unsigned char g[256],
- unsigned char b[256],
- int width,
- int height,
- int colors)
- {
- /* All set, let's do it. */
- picData = data;
- PCXEncode(ifp, width, height, colors, r, g, b, ReadPlanes );
- }
-
- /*****************************************************************************
- *
- * PCXENCODE.C - PCX Image compression interface
- *
- * PCXEncode( FName, GHeight, GWidth, Colors, Red, Green, Blue, GetPlanes )
- *
- *****************************************************************************/
-
- /* public */
-
- static void PCXEncode( NXStream * fp,
- int GWidth,
- int GHeight,
- int Colors,
- unsigned char Red[],
- unsigned char Green[],
- unsigned char Blue[],
- vfunptr GetPlanes)
- {
- int BytesPerLine;
- int Planes;
- int BitsPerPixel;
- unsigned char *buf;
- int i;
- int n;
- int y;
-
- /*
- * select number of planes and number of bits
- * per pixel according to number of colors
- */
- /*
- * 16 colors or less are handled as 1 bit per pixel
- * with 1, 2, 3 or 4 color planes.
- * more than 16 colors are handled as 8 bits per pixel
- * with 1 plane
- */
- if (Colors > 16) {
- BitsPerPixel = 8;
- Planes = 1;
- } else {
- BitsPerPixel = 1;
- if (Colors > 8)
- Planes = 4;
- else if (Colors > 4)
- Planes = 3;
- else if (Colors > 2)
- Planes = 2;
- else
- Planes = 1;
- }
-
- /*
- * Write the PCX header
- */
- Putbyte( 0x0a, fp); // .PCX magic number
- Putbyte( 0x05, fp); // PC Paintbrush version
- Putbyte( 0x01, fp); // .PCX run length encoding
- Putbyte( BitsPerPixel, fp); // bits per pixel
-
- Putword( 0, fp ); // x1 - image left
- Putword( 0, fp ); // y1 - image top
- Putword( GWidth-1, fp ); // x2 - image right
- Putword( GHeight-1, fp ); // y2 - image bottom
-
- Putword( GWidth, fp ); // horizontal resolution
- Putword( GHeight, fp ); // vertical resolution
-
- /*
- * Write out the Color Map for images with 16 colors or less
- */
- n = (Colors <= 16) ? Colors : 16;
- for (i = 0; i < n; ++i) {
- Putbyte( Red[i], fp );
- Putbyte( Green[i], fp );
- Putbyte( Blue[i], fp );
- }
- for (; i < 16; ++i) {
- Putbyte( 255, fp );
- Putbyte( 255, fp );
- Putbyte( 255, fp );
- }
-
- Putbyte( 0, fp); // reserved byte
-
- Putbyte( Planes, fp); // number of color planes
-
- BytesPerLine = ((GWidth * BitsPerPixel) + 7) / 8;
- Putword( BytesPerLine, fp ) ; // number of bytes per scanline
-
- Putword( 1, fp); // pallette info
-
- for (i = 0; i < 58; ++i) // fill to end of header
- Putbyte( 0, fp );
-
- buf = (unsigned char *)malloc( MAXPLANES * BytesPerLine );
-
- for (y = 0; y < GHeight; ++y) {
- (*GetPlanes)(y, GWidth, buf, Planes, BitsPerPixel);
-
- for (i = 0; i < Planes; ++i)
- PutPlane(fp, buf + (i * BytesPerLine), BytesPerLine);
- }
-
- /*
- * color map for > 16 colors is at end of file
- */
- if (Colors > 16) {
- Putbyte( 0x0c, fp); // magic for 256 colors
- for (i = 0; i < Colors; ++i) {
- Putbyte( Red[i], fp );
- Putbyte( Green[i], fp );
- Putbyte( Blue[i], fp );
- }
- for (; i < MAXCOLORS; ++i) {
- Putbyte( 255, fp );
- Putbyte( 255, fp );
- Putbyte( 255, fp );
- }
- }
- }
-
- static void PutPlane ( NXStream *fp,
- unsigned char *buf,
- int Size )
- {
- unsigned char *end;
- int c;
- int previous;
- int count;
-
- end = buf + Size;
-
- previous = *buf++;
- count = 1;
-
- while (buf < end)
- {
- c = *buf++;
- if (c == previous && count < 63) {
- ++count;
- continue;
- }
-
- if (count > 1 || (previous & 0xc0) == 0xc0) {
- count |= 0xc0;
- Putbyte ( count , fp );
- }
- Putbyte(previous, fp);
- previous = c;
- count = 1;
- }
-
- if (count > 1 || (previous & 0xc0) == 0xc0) {
- count |= 0xc0;
- Putbyte ( count , fp );
- }
- Putbyte(previous, fp);
- }
-
- static unsigned long PixMap[8][16] =
- {
- 0x00000000L, 0x00000080L, 0x00008000L, 0x00008080L,
- 0x00800000L, 0x00800080L, 0x00808000L, 0x00808080L,
- 0x80000000L, 0x80000080L, 0x80008000L, 0x80008080L,
- 0x80800000L, 0x80800080L, 0x80808000L, 0x80808080L,
- };
-
- static void ReadPlanes( int y,
- int width,
- unsigned char *buf,
- int planes,
- int bits)
- {
- // static pixel **pixels;
- static int first_time = 1;
- unsigned char *plane0, *plane1, *plane2, *plane3;
- int i, j, x;
-
- /*
- * 256 color, 1 plane, 8 bits per pixel
- */
- plane0 = picData + width * y;
- if (planes == 1 && bits == 8) {
- for (x = 0; x < width; ++x)
- // buf[x] = ppm_lookupcolor( cht, &pixels[y][x] );
- buf[x] = *(plane0 + x);
- return;
- }
-
- /*
- * must be 16 colors or less, 4 planes or less, 1 bit per pixel
- */
- if (first_time) {
- for (i = 1; i < 8; ++i)
- for (j = 0; j < 16; ++j)
- PixMap[i][j] = PixMap[0][j] >> i;
- first_time = 0;
- }
-
- i = (width + 7) / 8;
-
- plane0 = buf;
- plane1 = plane0 + i;
- plane2 = plane1 + i;
- plane3 = plane2 + i;
-
- i = 0;
- x = 0;
-
- while ( x < width ) {
- register unsigned long t;
-
- t = PixMap[0][ppm_lookupcolor( cht, &pixels[y][x++] )];
- t |= PixMap[1][ppm_lookupcolor( cht, &pixels[y][x++] )];
- t |= PixMap[2][ppm_lookupcolor( cht, &pixels[y][x++] )];
- t |= PixMap[3][ppm_lookupcolor( cht, &pixels[y][x++] )];
- t |= PixMap[4][ppm_lookupcolor( cht, &pixels[y][x++] )];
- t |= PixMap[5][ppm_lookupcolor( cht, &pixels[y][x++] )];
- t |= PixMap[6][ppm_lookupcolor( cht, &pixels[y][x++] )];
- t |= PixMap[7][ppm_lookupcolor( cht, &pixels[y][x++] )];
-
- plane0[i] = t;
- plane1[i] = t >> 8;
- plane2[i] = t >> 16;
- plane3[i++] = t >> 24;
- }
- }
-
- /*
- * Write out a word to the PCX file
- */
- static void Putword( int w,
- NXStream *fp)
- {
- NXPutc( fp, w & 0xff );
- NXPutc( fp, (w / 256) & 0xff );
- }
-
- /*
- * Write out a byte to the PCX file
- */
- static void Putbyte( int b,
- NXStream *fp )
- {
- NXPutc( fp, b & 0xff );
- }
-
- /* The End */
-